#ifndef _INPUT_BOX_H_JM_20120626
#define _INPUT_BOX_H_JM_20120626

#include "../RootBox.h"

namespace jm4bbx {
	struct InputBoxDescriptor  {

		static const groupType OUTPUT_GROUP;	
		static const columnType OUTPUT_COLUMN;
		static const outType OUT_ARC;

		static const char* INPUT_SPECIFICATION_PARAMETER_NAME;

	};
	/**
	 * Bazova trieda pre boxy nacitajuce data do modelu vypoctu.
	 * InputBox vyuziva schopnosti signalov zdedene od triedy {@link Box}. 
	 * Vstupny signal musi byt minimalne jeden (tem ktory spusti vypocet), 
	 * dalsie vstupne signaly a pripdne vystupne signaly su volitelne podla 
	 * poziadavkov modelu.
	 * InputBox ma jednu klasicku vystupnu skupinu, ktora nesie data vstupujuce 
	 * do mnodelu. Bazova trieda alokuje priestor (podla metody 
	 * {@link #getColumnSize()} pre vstupne data a odosiela 
	 * ich do vypoctu. Samotne obdraznie dat a nasledne naplnenie do struktur je 
	 * ponechane na potomkov v metode {@link #loadData()}.
	 *
	 * */
	//template<class BoxDescriptor>
	class InputBox : public Box/*<BoxDescriptor>*/ { 
	public:
		typedef InputBoxDescriptor BoxIO;
/*		static_assert(
			std::is_base_of<InputBoxDescriptor, BoxDescriptor>::value,
			"Parameter sablony (deskriptor boxu) musi byt potomok triedy InputBoxDescriptor!");	*/	

		InputBox(bobox::box_id_type id, 
			bobox::box_tid_type tid, bobox::request *req, 
			const bobox::parameters &params) 
			: Box(id, tid, req, params)
			, inputSpecification_("") {
				
				if (params.has_parameter(
					BoxIO::INPUT_SPECIFICATION_PARAMETER_NAME)) {
						params.get_parameter(
							BoxIO::INPUT_SPECIFICATION_PARAMETER_NAME, 
							inputSpecification_);
				}
		}

		/**
		 * Velkost stlpca (vsetkych stlpcov) == pocet riadkov.
		 * */
		virtual size_t getColumnSize() const = 0;


		virtual void initImpl() override {


			add_group(BoxIO::OUTPUT_GROUP, BoxIO::OUTPUT_COLUMN, 
				get_output_descriptors(BoxIO::OUT_ARC));

			initDataStructures();
			loadData();

			wait4SignalsIn();
		}

		virtual void sync_mach_etwas() override {
			//const group& g = get_group(BoxIO::INPUT_GROUP);
			//if (g.poisoned_) {
			//	//send_poisoned(bobox::outarc_index_type(OUTPUT_G1_COLUMN_1));
			//	//return;
			//}

			send(BoxIO::OUT_ARC, BoxIO::OUTPUT_GROUP);
			sendSignalsOut();
			wait4SignalsIn();
			//send_poisoned(BoxIO::OUT_ARC);
		}


	protected:
		std::string inputSpecification_;

		/**
		 * Natiahnutie dat do struktur boxu (stlpcov). Metoda sa vola vzdy
		 * po alokacii pamate a este pred samotnym odosielanim dat 
		 * dalsiemu boxu.
		 * */
		virtual void loadData() = 0;

	private :

		/// Inicalizacia datovych struktur pre data - alokacia pamate.
		void initDataStructures() {
				const size_t size = getColumnSize();
				allocate(BoxIO::OUTPUT_GROUP, size);
				get_group(BoxIO::OUTPUT_GROUP).setWritePosition(size);//wrpos_ = size;
		}
	};

}

#endif
